package com.inzone.fram.gray.common.rule;

import java.util.*;

/**
 * 匹配元数据上下文
 *
 * @author 丁常磊
 * @date 2021/8/23 16:38
 */
public class MatchingContext {

    /**
     * 记录当前线程中的匹配上下文
     */
    private static ThreadLocal<MatchingContext> MATCHING_CONTEXT_THREAD_LOCAL = new ThreadLocal<>();


    /**
     * 灰度标签请求头
     */
    public static final String GRAY_HEADER_TAGS = "inzone-gray-tags";

    /**
     * 灰度分组前缀
     */
    public static final String GRAY_HEADER_GROUPS = "inzone-gray-groups";

    /**
     * 标签集合
     */
    private Map<String, String> tagMap;

    /**
     * 所属分组
     */
    private List<String> groups;

    private String tagsText;
    private String groupsText;


    /**
     * 初始化
     */
    public static MatchingContext init() {
        if (!isInitialized()) {
            MatchingContext matchingContext = new MatchingContext();
            MATCHING_CONTEXT_THREAD_LOCAL.set(matchingContext);
            return matchingContext;
        }
        return current();
    }


    /**
     * 修改tag
     * 强制修改并不安全
     */
    public void forceSetTagMap(Map<String, String> tagMap) {
        this.tagMap = tagMap;
    }


    /**
     * 设置灰度组
     * 强制修改并不安全
     *
     * @param groups
     */
    public void forceSetGroups(List<String> groups) {
        this.groups = groups;
    }

    /**
     * 获取灰度组
     * 懒加载策略
     *
     * @return
     */
    public  List<String> getGroups() {
        if (this.groups == null) {
            String gv = this.groupsText;
            if (gv == null) {
                this.groups = Collections.emptyList();
            } else {
                this.groups = Arrays.asList(gv.split(","));
            }
        }
        return this.groups;
    }


    /**
     * 获取当前灰度头集合
     * 懒加载策略
     *
     * @return
     */
    public  Map<String, String> getTagMap() {
        if (this.tagMap == null) {
            String tagValue = this.tagsText;
            if (tagValue == null) {
                this.tagMap = Collections.emptyMap();
            } else {
                this.tagMap = Collections.unmodifiableMap(parseTagMap(tagValue));
            }
        }
        return this.tagMap;
    }


    /**
     * 获取当前上下文
     *
     * @return
     */
    public static MatchingContext current() {
        MatchingContext matchingContext = MATCHING_CONTEXT_THREAD_LOCAL.get();
        if (matchingContext == null) {
            throw new IllegalStateException("上下文尚未初始化");
        }
        return matchingContext;
    }

    /**
     * 封装map解析算法提高解析性能
     * 灰度参数格式
     * KEY = VALUE
     * 多个值使用&分隔
     * 例如: tag1=a&tag2=b
     *
     * @param s
     * @return
     */
    private static Map<String, String> parseTagMap(String s) {
        if ("".equals(s)) {
            return Collections.emptyMap();
        }
        int start = 0;
        Map<String, String> data = new HashMap<>();
        String key = null;
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            if (c == '&') {
                if (key != null) {
                    String value = s.substring(start, i);
                    data.put(key, value);
                }
                key = null;
                start = i + 1;
            } else if (c == '=') {
                key = s.substring(start, i);
                start = i + 1;
            }
        }
        if (key != null) {
            String value = s.substring(start);
            data.put(key, value);
        }
        return data;
    }

    public static void forceSetCurrent(MatchingContext context) {
        MATCHING_CONTEXT_THREAD_LOCAL.set(context);
    }

    /**
     * 判断当前是否初始化完成
     *
     * @return
     */
    public static boolean isInitialized() {
        return MATCHING_CONTEXT_THREAD_LOCAL.get() != null;
    }

    /**
     * 重置当前线程
     */
    public static void reset() {
        MATCHING_CONTEXT_THREAD_LOCAL.remove();
    }


    public void setTagsText(String tagsText) {
        this.tagsText = tagsText;
    }

    public void setGroupsText(String groupsText) {
        this.groupsText = groupsText;
    }


    public String getTagsText() {
        return tagsText;
    }

    public String getGroupsText() {
        return groupsText;
    }



}
